package tool

import (
	"context"
	"fmt"
	"github.com/minio/minio-go/v7"
	"github.com/minio/minio-go/v7/pkg/credentials"
	"io"
	"log"
	"path"
)

type MinioCos struct {
	Secret       string `yaml:"secret"`
	Key          string `yaml:"key"`
	Url          string `yaml:"url"`
	BucketName   string `yaml:"bucketname"`
	UseSSL       bool   `yaml:"useSSL"`
	BucketRegion string `yaml:"bucket_region"`
	ProxyUrl     string `yaml:"proxy_url"`
}

var ossCli *Client

func GetClient() *Client {
	return ossCli
}

type Client struct {
	conn         *minio.Client
	bucketName   string
	bucketRegion string
}

func OssInit(c MinioCos) {
	opts := minio.Options{
		Creds:  credentials.NewStaticV4(c.Key, c.Secret, ""),
		Secure: c.UseSSL,
	}

	cli, err := minio.New(c.Url, &opts)
	if err != nil {
		panic("minio连接错误: " + err.Error())
	}
	ossCli = &Client{conn: cli}
	err = ossCli.CreateBucket(context.Background(), c.BucketName, c.BucketRegion)
	if err != nil {
		log.Printf("oss create bucket err:%s", err.Error())
	}
}

func (o *Client) CreateBucket(ctx context.Context, name, region string) error {
	opts := minio.MakeBucketOptions{
		Region:        region,
		ObjectLocking: false,
	}

	err := o.conn.MakeBucket(ctx, name, opts)
	if err != nil {
		exists, _ := o.conn.BucketExists(ctx, name)
		if !exists {
			return err
		}
	}

	o.bucketName = name
	o.bucketRegion = region

	return nil
}

func (o *Client) FPubObject(objectName, filePath, contextType string) error {
	opts := minio.PutObjectOptions{
		ContentType: contextType,
	}
	ctx := context.Background()
	uploadInfo, err := o.conn.FPutObject(ctx, o.bucketName, objectName, filePath, opts)
	if err != nil {
		log.Println("上传失败：", err)
		return err
	}
	fmt.Printf("upload info:%+v\n", uploadInfo)
	return nil
}

func (o *Client) PubObject(ctx context.Context, reader io.Reader, objectName string, size int64) error {
	opts := minio.PutObjectOptions{
		ContentType: getContentTypeFromObjectName(objectName),
	}
	info, err := o.conn.PutObject(ctx, o.bucketName, objectName, reader, size, opts)
	if err != nil {
		log.Println("上传失败：", err)
		return err
	}
	fmt.Printf("upload info:%+v\n", info)
	return nil
}

func (o *Client) GetObject(fileName string) (*minio.Object, error) {
	opts := minio.GetObjectOptions{}
	ctx := context.Background()
	object, err := o.conn.GetObject(ctx, o.bucketName, fileName, opts)
	if err != nil {
		log.Println("上传失败：", err)
		return nil, err
	}
	fmt.Printf("upload info:%+v\n", fileName)
	return object, nil
}

func (o *Client) RemoveObject(objectName string) error {
	opts := minio.RemoveObjectOptions{
		GovernanceBypass: true,
	}
	ctx := context.Background()
	err := o.conn.RemoveObject(ctx, o.bucketName, objectName, opts)
	if err != nil {
		return err
	}

	return nil
}
func getContentTypeFromObjectName(objectName string) string {
	var contentTypeMap = map[string]string{
		".png":  "image/png",
		".jpeg": "image/jpeg",
		".jpg":  "image/jpeg",
	}
	return contentTypeMap[path.Ext(objectName)]
}
